//
// Created by YueChuan on 2023/5/4.
//

#ifndef YUECHUAN_SERVLET_H
#define YUECHUAN_SERVLET_H

#include <memory>
#include "http.h"
#include "http_session.h"
#include "util.h"
#include <unordered_map>
#include <fnmatch.h>

namespace yuechuan {
    namespace http {
        class Servlet {
        public:
            typedef std::shared_ptr<Servlet> ptr;

            Servlet(const std::string &name) : m_name(name) {}

            virtual ~Servlet() {}

            /**
             * @brief 处理请求，纯虚函数
             * @param request HTTP请求
             * @param response HTTP响应
             * @param session HTTP连接
             * @return int32_t 是否处理成功
             */
            virtual int32_t handle(HttpRequest::ptr request, HttpResponse::ptr response, HttpSession::ptr session) = 0;


            /**
             * @brief 返回servlet名称
             * @return
             */
            const std::string &getName() const { return m_name; }

        protected:
            /// 名称
            std::string m_name;
        };

        /**
         * @brief 函数式servlet
         */
        class FunctionServlet : public Servlet {
        public:
            typedef std::shared_ptr<FunctionServlet> ptr;
            /// 函数回调类型定义
            typedef std::function<int32_t(HttpRequest::ptr request, HttpResponse::ptr response,
                                          HttpSession::ptr session)> callback;

            /**
             * @brief 含参构造函数
             * @param cb 回调函数
             */
            FunctionServlet(callback cb);

            virtual int32_t handle(HttpRequest::ptr request, HttpResponse::ptr response,
                                   HttpSession::ptr session) override;

        private:
            /// 回调函数
            callback m_cb;
        };

        class IServletCreator {
        public:
            typedef std::shared_ptr<IServletCreator> ptr;

            virtual ~IServletCreator() {}

            virtual Servlet::ptr get() const = 0;

            virtual std::string getName() const = 0;
        };

        class HoldServletCreator : public IServletCreator {
        public:
            typedef std::shared_ptr<HoldServletCreator> ptr;

            HoldServletCreator(Servlet::ptr servlet) : m_servlet(servlet) {}

            Servlet::ptr get() const override {
                return m_servlet;
            }

            std::string getName() const override {
                return m_servlet->getName();
            }

        private:
            Servlet::ptr m_servlet;
        };

        template<class T>
        class ServletCreator : public IServletCreator {
        public:
            typedef std::shared_ptr<ServletCreator> ptr;

            ServletCreator() {

            }

            Servlet::ptr get() const override {
                return Servlet::ptr(new T);
            }

            std::string getName() const override {
                return TypeToName<T>();
            }
        };

        /**
         * @brief Servlet分发器
         */
        class ServletDispatch : public Servlet {
        public:
            typedef std::shared_ptr<ServletDispatch> ptr;
            typedef RWMutex RWMutexType;

            /**
             * @brief 无参构造函数
             */
            ServletDispatch();

            int32_t handle(HttpRequest::ptr request, HttpResponse::ptr response, HttpSession::ptr session) override;

            /**
             * @brief 添加Servlet
             * @param uri uri
             * @param servlet servlet对象
             */
            void addServlet(const std::string &uri, Servlet::ptr servlet);

            /**
             * @brief 添加函数式servlet
             * @param uri uri
             * @param cb FunctionServlet回调函数
             */
            void addServlet(const std::string &uri, FunctionServlet::callback cb);

            /**
             * @brief 添加模糊匹配servlet
             * @param uri 模糊匹配
             * @param servlet servlet
             */
            void addGlobServlet(const std::string &uri, Servlet::ptr servlet);

            /**
             * @brief 添加模糊匹配Function类型的servlet
             * @param uri 模糊匹配
             * @param cb 回调函数
             */
            void addGlobServlet(const std::string &uri, FunctionServlet::callback cb);


            void addServletCreator(const std::string &uri, IServletCreator::ptr creator);

            void addGlobServletCreator(const std::string &uri, IServletCreator::ptr creator);

            template<class T>
            void addServletCreator(const std::string &uri) {
                addServletCreator(uri, std::make_shared<ServletCreator<T>>());
            }

            template<class T>
            void addGlobServletCreator(const std::string &uri) {
                addGlobServletCreator(uri, std::make_shared<ServletCreator<T> >());
            }

            /**
             * @brief 删除servlet
             * @param uri uri
             */
            void delServlet(const std::string &uri);

            /**
             * @brief 删除模糊匹配servlet
             * @param uri uri
             */
            void delGlobServlet(const std::string &uri);

            /**
             * @brief 获取默认的servlet
             * @return
             */
            Servlet::ptr getDefault() const { return m_default; }

            /**
             * @brief 设置默认的servlet
             * @param v
             */
            void setDefault(Servlet::ptr v) { m_default = v; }

            /**
             * @brief 通过uri来获取Servlet
             * @param uri
             * @return Servlet::ptr 返回对应的servlet
             */
            Servlet::ptr getServlet(const std::string &uri);

            /**
             * @brief 通过uri模糊匹配servlet
             * @param uri uri
             * @return Servlet::ptr 返回对应的servlet
             */
            Servlet::ptr getGlobServlet(const std::string &uri);

            /**
             * @brief 通过uri获取servlet
             * @param uri uri
             * @return 优先精确匹配，再次模糊匹配，最后返回默认
             */
            Servlet::ptr getMatchServlet(const std::string &uri);

            void listAllServletCreator(std::map<std::string, IServletCreator::ptr> &infos);

            void listAllGlobServletCreator(std::map<std::string, IServletCreator::ptr> &infos);

        private:
            ///读写互斥量
            RWMutexType m_mutex;
            /// 精确匹配servlet map
            std::unordered_map<std::string, IServletCreator::ptr> m_datas;

            /// 模糊匹配servlet map
            std::vector<std::pair<std::string, IServletCreator::ptr> > m_globs;
            /// 默认的servlet ， 所有路径都没有匹配成功时使用
            Servlet::ptr m_default;
        };

        class NotFoundServlet : public Servlet {
        public:
            typedef std::shared_ptr<NotFoundServlet> ptr;

            NotFoundServlet(const std::string &name);

            int32_t handle(HttpRequest::ptr request, HttpResponse::ptr response, HttpSession::ptr session) override;

        private:
            /// servlet名称
            std::string m_name;
            /// 正文
            std::string m_content;
        };

    }
}


#endif //YUECHUAN_SERVLET_H
